<template>
  <div
    class="node node-generic"
    :class="{ muted: isMuted }"
    :style="
      {
        '--node-color': primaryColor,
        '--node-color-strong': primaryStrong,
        '--node-bg-soft': softBg,
        '--node-shadow': shadowRgba,
      } as any
    "
  >
    <div class="node-bar"></div>
    <div class="node-content">
      <div class="node-main">
        <!-- 悬停工具栏（执行 / 屏蔽 / 删除） -->
        <NodeToolbar
          :node-id="id"
          :show-execute="true"
          :show-mute="true"
          :show-delete="true"
          :muted="isMuted"
        />
        <div class="node-title">{{ data.label || "人工节点" }}</div>
        <div class="node-desc">{{ data.description || "人工处理节点" }}</div>
        <!-- 表单摘要：展示 name=value -->
        <div v-if="kvPairs.length" class="kv-list">
          <div v-for="it in kvPairs" :key="it.k" class="kv-item">
            <span class="kv-key">{{ it.k }}</span>
            <span class="kv-sep">=</span>
            <span class="kv-val">{{ it.v }}</span>
          </div>
        </div>
        <!-- 出参展示：按 value : key 顺序，整体右对齐 -->
        <div
          v-if="outputsPairs.length"
          class="kv-list kv-right"
          style="margin-top: 6px"
        >
          <div v-for="it in outputsPairs" :key="it.key" class="kv-item">
            <span class="kv-val">{{ it.key }}</span>
            <span class="kv-sep">:</span>
            <span class="kv-key">{{ it.value }}</span>
          </div>
        </div>
      </div>
    </div>
    <!-- 左入 -->
    <Handle
      type="target"
      :position="Position.Left"
      id="target"
      class="node-handle node-handle-left"
    />
    <!-- 右目标（用于右半自动吸附） -->
    <Handle
      type="target"
      :position="Position.Right"
      id="target-right"
      class="node-handle node-handle-right"
    />
    <!-- 右出（单一出口） -->
    <Handle
      type="source"
      :position="Position.Right"
      id="source"
      class="node-handle node-handle-right"
      :style="{ top: '50%' }"
    />
    <!-- 屏蔽遮罩层（整卡片覆盖） -->
    <div v-if="isMuted" class="mute-mask"></div>
  </div>
</template>

<script setup lang="ts">
import { defineProps, computed } from "vue";
import { Handle, Position } from "@vue-flow/core";
import { useVueFlow } from "@vue-flow/core";
import { useWorkflowVariables } from "@/components/workflow/useWorkflowVariables";
import NodeToolbar from './NodeToolbar.vue'

interface Props {
  id?: string;
  data: {
    label?: string;
    description?: string;
    category?: string;
    formData?: Record<string, any>;
    outputs?: Array<{ key: string; name?: string }>;
  };
}

const props = defineProps<Props>();
const { findNode } = useVueFlow();

const catColors: Record<string, string> = {
  form: "#3b82f6",
  approval: "#f59e42",
  basic: "#10b981",
  custom: "#a855f7",
  condition: "#f43f5e",
  control: "#6366f1",
};

function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
  const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  if (!m) return null;
  return {
    r: parseInt(m[1], 16),
    g: parseInt(m[2], 16),
    b: parseInt(m[3], 16),
  };
}
function rgba(hex: string, a: number): string {
  const rgb = hexToRgb(hex);
  if (!rgb) return hex;
  const { r, g, b } = rgb;
  return `rgba(${r}, ${g}, ${b}, ${a})`;
}

const primaryColor = computed(() => {
  const cat = (props as any).data?.category as string | undefined;
  if (cat && catColors[cat]) return catColors[cat];
  return catColors.basic;
});
const primaryStrong = computed(() => primaryColor.value);
const softBg = computed(() => rgba(primaryColor.value, 0.06));
const shadowRgba = computed(() => rgba(primaryColor.value, 0.08));

// 变量映射：value(${nodeKey,key}) -> display(${节点名称,key})
const { processVariables, outputVariables, systemVariables } =
  useWorkflowVariables();
const varDisplayMap = computed<Record<string, string>>(() => {
  const map: Record<string, string> = {};
  const all = [
    ...(processVariables?.value || []),
    ...(outputVariables?.value || []),
    ...(systemVariables?.value || []),
  ];
  for (const it of all) {
    const val = String((it as any)?.value ?? "");
    if (!val) continue;
    const dis = String((it as any)?.display ?? val);
    map[val] = dis;
  }
  return map;
});

// 生成 name=value 摘要，最多展示前 4 项
const kvPairs = computed(() => {
  const fd: any = (props as any).data?.formData || {};
  const entries = Object.entries(fd)
    .filter(([k]) => k !== undefined && k !== null && String(k).trim() !== "")
    .map(([k, v]) => ({ k: String(k), v: formatVal(v) }));
  return entries.slice(0, 4);
});

// 出参对（按 value key 顺序渲染），value 使用 name，key 使用 key
const outputsPairs = computed(() => {
  const list = Array.isArray((props as any).data?.outputs)
    ? ((props as any).data?.outputs as Array<any>)
    : [];
  return list
    .filter((it) => it && String(it.key || "").trim() !== "")
    .map((it) => ({ key: String(it.key), value: String(it.name || "") }));
});

function formatVal(v: any): string {
  if (v === null || v === undefined) return "";
  if (Array.isArray(v)) return v.map((x) => formatVal(x)).join(", ");
  if (typeof v === "object") return JSON.stringify(v);
  const s = String(v);
  const dis = varDisplayMap.value[s];
  return dis ?? s;
}

// 工具栏交互
const isMuted = computed<boolean>(() => {
  try {
    const id = String((props as any).id || "");
    const n = id ? findNode(id) : null;
    return Boolean((n as any)?.data?.muted);
  } catch (e) {
    return false;
  }
});

// 事件改由 NodeToolbar 内部处理
</script>

<style scoped>
.node {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 2px 12px var(--node-shadow, rgba(0, 0, 0, 0.08));
  min-width: 240px;
  max-width: 360px;
  border: 1.5px solid #e5e7eb;
  overflow: visible;
  margin: 0;
  padding: 0;
  transition:
    box-shadow 0.2s,
    border 0.2s;
  cursor: pointer;
  position: relative;
}

/* 悬停时显示来自子组件的工具栏 */
.node:hover :deep(.node-toolbar) {
  display: flex;
}
.node-bar {
  width: 8px;
  background: var(--node-color, #10b981);
  border-top-left-radius: 14px;
  border-bottom-left-radius: 14px;
}
.node-content {
  display: flex;
  align-items: flex-start;
  padding: 14px 10px 14px 16px;
  flex: 1;
}
.node-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
.node-title {
  font-weight: 600;
  color: var(--node-color-strong, #059669);
  font-size: 16px;
  margin-bottom: 2px;
}
.node-desc {
  color: var(--node-color, #10b981);
  font-size: 13px;
  line-height: 1.3;
  margin-bottom: 4px;
}

/* 表单摘要样式 */
.kv-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 4px;
}
.kv-item {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: #64748b;
}
/* 遮罩样式改为全局定义，见 NodeToolbar.vue 未 scoped 样式块 */
.kv-key {
  color: var(--node-color-strong, #059669);
  font-weight: 500;
}
.kv-sep {
  color: var(--node-color, #10b981);
  opacity: 0.6;
}
.kv-val {
  color: #64748b;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 出参右对齐 */
.kv-right {
  align-items: flex-end;
}
.kv-right .kv-item {
  justify-content: flex-end;
}

/* 连接点样式 */
.node-handle {
  width: 12px !important;
  height: 12px !important;
  background: var(--node-color, #10b981) !important;
  border: 2px solid #fff !important;
  border-radius: 50% !important;
  position: absolute !important;
  transform: translate(-50%, -50%) !important;
}
.node-handle-left {
  left: -6px !important;
  top: 50% !important;
}
.node-handle-right {
  right: -6px !important;
  top: 50% !important;
}
.node-handle:hover {
  background: var(--node-color-strong, #059669) !important;
  transform: translate(-50%, -50%) scale(1.2) !important;
}

/* 屏蔽态样式 */
/* 屏蔽态：整体降低不透明度并微灰 */
.node.muted {
  opacity: 0.6;
  filter: grayscale(0.15);
}
</style>
